-- Author: Compumaster
with data_library; use data_library;
with ada.text_io;  use ada.text_io;
with interfaces.c; use interfaces.c;
with Ada.Float_Text_IO;     use Ada.Float_Text_IO;
with Ada.Integer_Text_IO;     use Ada.Integer_Text_IO;
with Ada.Strings.Fixed ;use Ada.Strings.Fixed ;

package body bus_stops is
    --Tache Bus_stop
    task body bus_stop is
        --id_bus_stop : integer;
        
        --  Specification du package bus_stop_info 
        package bus_stop_info is
        function  getBus_stopId return Integer;
            procedure setBus_stopId(id : in Integer);
            end bus_stop_info;
        
        
        --Specification de la tache cyclique permetant de decrementer le temps d'attente des bus_stops
        task descrease_waiting_time is
        end descrease_waiting_time;
        
        --Specification de l'objet protege permettant de gerer la liste des horaires
        protected schedules is
            
            --Specification de la procedure interne permettant d'afficher la liste d'horaires
            procedure displaySchedules_array;
            
            --Specification de la procedure interne permettant de modifier un horaire present dans la liste
            procedure editArrivalTime(indice : in integer;s : in T_Schedule);
            
            --Specification de la procedure interne permettant d'ajouter un horaire dans la liste
            procedure addArrivalTime(s : in T_Schedule);
            
            --Specification de la fonction d'entree permettant de modifier la liste des horaires
            entry set_arrival_time(s : in T_Schedule); 
            
            --Specification de la procedure interne permettant de decrementer les temps d'attente de tous les horaires presents dans la liste
            procedure descrease_waiting_time;
            
        private
            
            --Liste d'horaires
            schedules_array : T_Schedules(5);
            
        end schedules;
  
  
          --Corps du package bus_stop_info
        package body bus_stop_info is
			bus_stopId : integer;
			function  getBus_stopId return Integer is
            begin
                return bus_stopId;
            end getBus_stopId;
            procedure setBus_stopId(id : in Integer) is
            begin
                bus_stopId := id;
            end setBus_stopId;
            end bus_stop_info;
  
       --Corps de l'objet protege permettant de gerer la liste des horaires      
        protected body schedules is
            
            --Corps de la procedure interne permettant d'afficher la liste d'horaires
            procedure displaySchedules_array is
                i : integer;
                waiting_temp: Float;
		fresultat : file_type ; -- les fichiers donnee et resultat
		--fileName :string(1..11) ;
            --k : string(1..2);
            begin
		--k:=Integer'image(bus_stop_info.getBus_stopId);
		--fileName:="arret"&k&".html";
		create (fresultat, out_file,"arret"&Trim (Integer'Image (bus_stop_info.getBus_stopId), Ada.Strings.Left)&".html") ; -- ouverture en ecriture
	--close (fresultat) ;
                i:=1;
                waiting_temp := schedules_array.Tab(i).waiting_time * 3600.0; -- afficher le waiting time en secondes
		put(fresultat,"<HTML><HEAD><TITLE>Bus Network</TITLE>");
		put_line(fresultat,"<meta http-equiv=refresh content=1;arret"&Trim (Integer'Image (bus_stop_info.getBus_stopId), Ada.Strings.Left)&".html") ;
		put_line(fresultat,"<style type=text/css>");
		put_line(fresultat,"<!--");
		put_line(fresultat,"body {background-image: url(pics/bg.jpg);}");
		put_line(fresultat,"-->");
		put_line(fresultat,"</style>");
		put_line(fresultat,"</HEAD><BODY background-repeat=no-repeat >");
		put_line(fresultat,"<h1 align=center>Horaires du BusStop 2<br><br></h1>");
		put_line(fresultat,"<table width=493 border=1 align=center><tr>");
		put_line(fresultat,"<td width=130><div align=center>Num&eacute;ro de la ligne </div></td>");
		put_line(fresultat,"<td width=169><div align=center>Temps d'attente (Secondes)</div></td>");
		put_line(fresultat,"<td width=172><div align=center>Informations</div></td></tr>");
		put_line(fresultat,"");
		put_line(fresultat,"");
               
                while (i<=schedules_array.Sommet)
                        loop
				
					put_line(fresultat,"<tr>");
					put(fresultat,"<td><div align=center>");
					put(fresultat,schedules_array.Tab(i).line_number);
					put_line(fresultat,"</div></td>");
					put(fresultat,"<td><div align=center>");
					put(fresultat,schedules_array.Tab(i).waiting_time*3600.0, Aft => 2,Exp => 0);
					put_line(fresultat,"</div></td>");
					case (schedules_array.Tab(i).info) is
					when 0 =>
					put_line(fresultat,"<td><div align=center>A l'heure</div></td>");
					when 1 =>
					put_line(fresultat,"<td><div align=center>En avance</div></td>");
					when 2 =>
					put_line(fresultat,"<td><div align=center>En retard</div></td>");
					when others =>
					put_line(fresultat,"<td><div align=center>Erreur info</div></td>");
					end case;
	
					--Ligne provoquant l'erreur
					--put(to_ada(schedules_array.Tab(i).info.all));
					put_line(fresultat,"");
                    i:=i+1;  
		put_line(fresultat,"</tr>");
                end loop;
                put_line(fresultat,"</table></BODY></HTML>");
close (fresultat) ;
-- put("Waiting time: ");put(waiting_temp, Aft => 2,Exp => 0);
            end displaySchedules_array;
            
            --Corps de la procedure interne permettant de modifier un horaire present dans la liste
            procedure editArrivalTime(indice : in integer;s : in T_Schedule) is    
                      
            begin
                
                schedules_array.Tab(indice):=s;
                null;
                
            end editArrivalTime;
            
            --Corps de la procedure interne permettant d'ajouter un horaire dans la liste
            
            procedure addArrivalTime(s : in T_Schedule) is
                
            begin
      --      put_line("add somment avt : "&integer'image(schedules_array.Sommet));
                schedules_array.Sommet:=schedules_array.Sommet+1;
        --    put_line("add somment avt : "&integer'image(schedules_array.Sommet));                
                schedules_array.Tab(schedules_array.Sommet):=s;
                null;
                
            end addArrivalTime;
            
            --Corps de la fonction d'entree permettant de modifier la liste des horaires
            
            entry set_arrival_time(s : in T_Schedule) when true is
                
                i : integer;
                find : boolean;  
                
                  
            begin
                
                i:=1;
                find:=false;
                --Si la liste n'est pas vide
                if (schedules_array.Sommet>0)
                        then
                    --On verifie si l'horaire est deja present dans la liste
                    while (i<=schedules_array.Sommet and find /= true)
                            loop
                        --Si c'est le cas, on modifie l'horaire present
                        if (schedules_array.Tab(i).line_number=s.line_number)        
                                then
                            editArrivalTime(i,s);
                            find:=true;
                       
                            displaySchedules_array;
                        end if;  
                        i:=i+1;  
                    end loop;
                    --Sinon on le rajoute a la liste
                    if (find /= true)
                            then
                        addArrivalTime(s);
                        displaySchedules_array;
                    end if;
                    --Si la liste est vide on rajoute directement l'horaire
                else
                    addArrivalTime(s);
                    displaySchedules_array;
                end if;
                
                null;
                
            end set_arrival_time;
            
            --Corps de la procedure interne permettant de decrementer les temps d'attente de tous les horaires presents dans la liste
            
            procedure descrease_waiting_time is
                
                i,j: integer;
                
            begin
                
                i:=1;

                --Si la liste n'est pas vide
                if (schedules_array.Sommet>0)
                        then
                    --On la parcourt pour decrementer les temps d'attente de chaque horaire s'il n'est pas nul
                    while (i<=schedules_array.Sommet)
                            loop
                        if (schedules_array.Tab(i).waiting_time>0.0)
                                then
                            schedules_array.Tab(i).waiting_time:=schedules_array.Tab(i).waiting_time-(1.0/60.0);
                            else
                            schedules_array.Sommet:=schedules_array.Sommet-1;
                            j:=i;
                            while (j<=schedules_array.Sommet)
                            loop
                            schedules_array.Tab(j):=schedules_array.Tab(j+1);
                                 j:=j+1;
                            end loop;
                        end if;
                        i:=i+1;  
                    end loop;
                end if;
                
            end descrease_waiting_time;
            
        end schedules;
        
--procedure setId_bus_stop(id : in integer) is
--begin
--id_bus_stop:=id;
--end setId_bus_stop;
--function getId_bus_stop return integer is
--begin
--return  id_bus_stop;
--end getId_bus_stop;

        --Corps de la tache cyclique permetant de decrementer le temps d'attente des bus_stops  
        
        task body descrease_waiting_time is     
             
        begin
            
            loop
                delay 1.0;
                schedules.descrease_waiting_time;
            end loop;
            
        end descrease_waiting_time;
        
        
        
    begin
        
        loop
         select
            --Creation du bus_stop (ne sera appele qu'une fois)
            accept create(id: in Integer) do
                bus_stop_info.setBus_stopId(id);
            end create;
        or
        accept getID(id : out integer) do
        	id:=bus_stop_info.getBus_stopId;
        	end getId;
        or
            accept set_arrival_time(s : in ptr_T_Schedule) do
                schedules.set_arrival_time(s.all);
            end;
            end select;
        end loop;
        null;
        
    end bus_stop;
    
begin
    
    null;
    
end bus_stops;
